import { isArray, uuid } from './utils'
import { isCssVariableName } from './regexUtil'
import Vue from 'vue'
import library from '../library'
import { PageDom, ComponentItemExt, MpdConfig, ConfigDetailType } from '../library/page-object'
import { mpdMessage } from './messageUtil'
import _ from 'lodash'

/**
 * 一维数组转对象
 * @param arr 需要转换的数组对象
 * @param keyField 作为key的字段名
 * @param valueField 作为value的字段名
 * @returns
 */
export const arrayToObj = function (
  arr: Array<{ [key: string]: any }>,
  keyField: string = 'key',
  valueField: string = 'value'
): { [key: string]: any } {
  if (!isArray(arr)) {
    return {}
  }
  const obj: { [key: string]: any } = {}
  arr.forEach((item) => {
    if (isCssVariableName(item[keyField]) && item[valueField]) {
      obj[item[keyField]] = item[valueField]
    }
  })
  return obj
}
/**
 * 初始化dom对象的默认值
 * @param {PageDom} domItem
 */
export const initDomValue = function (domItem: PageDom) {
  // 节点名称
  Vue.set(domItem, 'title', domItem.title || '')
  // 组件配置:页面dom配置
  if (domItem.mpdConfig) {
    // 组件配置:使用的组件名
    Vue.set(domItem.mpdConfig, 'component', domItem.mpdConfig.component || domItem.id)
    // 组件配置:双向绑定属性
    Vue.set(domItem.mpdConfig, 'model', domItem.mpdConfig.model || {})
    // 组件配置:传递的属性
    Vue.set(domItem.mpdConfig, 'attr', domItem.mpdConfig.attr || {})
    // 组件配置:class
    Vue.set(domItem.mpdConfig, 'class', domItem.mpdConfig.class || '')
    // 组件配置:style
    Vue.set(domItem.mpdConfig, 'style', domItem.mpdConfig.style || [])
    // 组件配置:v-if
    Vue.set(domItem.mpdConfig, 'vIf', domItem.mpdConfig.vIf || '')
    // 组件配置:v-show
    Vue.set(domItem.mpdConfig, 'vShow', domItem.mpdConfig.vShow || '')
    // 组件配置:v-on绑定的事件
    Vue.set(domItem.mpdConfig, 'event', domItem.mpdConfig.event || {})
    // 组件配置:text内容
    Vue.set(domItem.mpdConfig, 'text', domItem.mpdConfig.text || '')
    // 组件配置:slot内容
    if (!domItem.mpdConfig.slot) {
      const comConfig: PageDom = <PageDom>library.getLibraryDataMap(domItem.mpdConfig.component)
      if (comConfig && comConfig.mpdConfig && comConfig.mpdConfig.slot) {
        Vue.set(domItem.mpdConfig, 'slot', _.cloneDeep(comConfig.mpdConfig.slot))
      }
    } else if (domItem.mpdConfig.slot.length > 0) {
      domItem.mpdConfig.slot.forEach((item) => {
        initDomValue(item)
      })
    }
    // 组件配置:记录一些属性用的配置，用于设计器配置
    Vue.set(domItem.mpdConfig, 'configTmp', domItem.mpdConfig.configTmp || {})
  } else {
    const mpdConfig: MpdConfig = {
      component: domItem.id,
      model: {},
      attr: {},
      class: '',
      style: [],
      vIf: '',
      vShow: '',
      event: {},
      configTmp: {}
    }
    Vue.set(domItem, 'mpdConfig', mpdConfig)
  }
  // 子节点
  Vue.set(domItem, 'children', domItem.children || [])
  // id唯一标识，由uuid生成
  if (!domItem.id || domItem.id.length !== 36) {
    Vue.set(domItem, 'id', uuid())
  }
  // 将componentConfig的配置转换一下
  transformComponentConfig(domItem)
  // 移除扩展参数
  delete domItem.ext
  // 继续初始化子节点
  initArrayDomValue(domItem.children)
}
/**
 * 初始化数组dom对象的默认值
 * @param {Array} arrayDomItem
 */
export const initArrayDomValue = function (arrayDomItem?: Array<PageDom>): void {
  if (arrayDomItem && isArray(arrayDomItem) && arrayDomItem.length > 0) {
    arrayDomItem.forEach((item) => {
      initDomValue(item)
    })
  }
}
/**
 * 转换组件配置
 * @param {PageDom} domItem
 */
export const transformComponentConfig = function (domItem: PageDom): void {
  if (domItem.ext && domItem.ext.componentConfig) {
    domItem.ext.componentConfig.forEach((item) => {
      if (domItem.mpdConfig && item.defaultValue !== undefined) {
        Vue.set(domItem.mpdConfig[item.type] as object, item.name, item.defaultValue)
      }
    })
  }
}
/**
 * 是否含有对应的配置属性
 * @param domItem
 * @returns boolean
 */
export const hasConfigAttr = function (domItem: PageDom, attr: string): boolean {
  if (domItem.mpdConfig) {
    return domItem.mpdConfig.hasOwnProperty(attr)
  }
  return false
}
/**
 * 是否可以添加到子列表
 * @param {PageDom} parent 父元素
 * @param {PageDom} item 要判断的元素
 * @returns {Boolean}
 */
export const isCanPushChildren = function (parent: PageDom, item: PageDom): Boolean {
  const parentMpdConfig: MpdConfig = parent.mpdConfig || {}
  const foundParentData: PageDom = <PageDom>library.getLibraryDataMap(parentMpdConfig.component || parent.id)
  const foundItemData: PageDom = <PageDom>(
    library.getLibraryDataMap(item.mpdConfig ? item.mpdConfig.component || item.id : item.id)
  )
  let msg: string = ''
  const itemMpdConfig: MpdConfig = item.mpdConfig || {}
  if (!foundParentData) {
    msg = `没有在组件库中找到【${parent.title}(${parentMpdConfig.component})】的配置`
  } else if (!foundItemData) {
    msg = `没有在组件库中找到【${item.title}(${itemMpdConfig.component})】的配置`
  } else if (foundParentData.ext && foundParentData.ext.hasOwnProperty('childrenComponent')) {
    // 判断子元素配置
    const extData: ComponentItemExt = foundParentData.ext
    if (
      extData.childrenComponent &&
      extData.childrenComponent.length > 0 &&
      !extData.childrenComponent.includes(item.id) &&
      !(itemMpdConfig.component && extData.childrenComponent.includes(itemMpdConfig.component))
    ) {
      msg = `只能放入以下组件【${extData.childrenComponent.join(',')}】`
    }
  } else {
    msg = `没有配置属性【mpdConfig.childrenComponent】`
  }
  // 判断父元素配置
  if (
    !msg &&
    foundItemData.ext &&
    foundItemData.ext.hasOwnProperty('parentComponent') &&
    (foundItemData.ext.parentComponent as string[]).length > 0
  ) {
    const extData: ComponentItemExt = foundItemData.ext
    if (
      extData.parentComponent &&
      !extData.parentComponent.includes(parent.id) &&
      !extData.parentComponent.includes(<string>parentMpdConfig.component)
    ) {
      msg = `子元素只能放入到以下组件【${extData.parentComponent.join(',')}】`
    }
  }
  if (msg) {
    const msgPrefix = `目标元素【${parent.title}(${parentMpdConfig.component})】不能拖入子元素【${item.title}】，原因：`
    mpdMessage.error(msgPrefix + msg)
  }
  return !msg
}
/**
 * 删除单个配置对象
 * @param item  需要删除的对象
 * @param configArray 需要删除的数组元素
 * @param field 比较的字段
 * @returns
 */
export const deleteItem = function (item: any, configArray: Array<any> = [], field: string = 'id'): boolean {
  for (const index in configArray) {
    if (configArray[index][field] === item[field]) {
      configArray.splice(index as unknown as number, 1)
      return true
    }
    if (configArray[index].mpdConfig.slot && configArray[index].mpdConfig.slot.length > 0) {
      if (deleteItem(item, configArray[index].mpdConfig.slot, field)) {
        return true
      }
    }
    if (configArray[index].children && configArray[index].children.length > 0) {
      if (deleteItem(item, configArray[index].children, field)) {
        return true
      }
    }
  }
  return false
}
/**
 * 选中item，如果不传则是取消选中
 * @param selectPageNodeDom 选中的缓存对象
 * @param item 选中节点的item
 * @param slotItem 选中节点的slotItem
 */
export const selectItem = function (selectPageNodeDom: any, item: PageDom, slotItem: PageDom) {
  if (item) {
    selectPageNodeDom.item = item
    selectPageNodeDom.slotItem = slotItem || {}
  } else {
    selectPageNodeDom.item = {}
    selectPageNodeDom.slotItem = {}
  }
}
/**
 * 优化mpdPageConfig json结构，主要删除无用的属性，让保存的json体积更小
 * @param mpdPageConfig 页面配置
 * @returns
 */
export const optimizeMpdPageConfig = function (mpdPageConfig: PageDom): PageDom {
  if (mpdPageConfig.mpdConfig) {
    if (!mpdPageConfig.mpdConfig.model || Object.keys(mpdPageConfig.mpdConfig.model).length === 0) {
      delete mpdPageConfig.mpdConfig.model
    }
    if (!mpdPageConfig.mpdConfig.attr || Object.keys(mpdPageConfig.mpdConfig.attr).length === 0) {
      delete mpdPageConfig.mpdConfig.attr
    }
    if (!mpdPageConfig.mpdConfig.class) {
      delete mpdPageConfig.mpdConfig.class
    }
    if (!mpdPageConfig.mpdConfig.style || mpdPageConfig.mpdConfig.style.length === 0) {
      delete mpdPageConfig.mpdConfig.style
    }
    if (!mpdPageConfig.mpdConfig.vIf) {
      delete mpdPageConfig.mpdConfig.vIf
    }
    if (!mpdPageConfig.mpdConfig.vShow) {
      delete mpdPageConfig.mpdConfig.vShow
    }
    if (!mpdPageConfig.mpdConfig.event || Object.keys(mpdPageConfig.mpdConfig.event).length === 0) {
      delete mpdPageConfig.mpdConfig.event
    }
    if (!mpdPageConfig.mpdConfig.text) {
      delete mpdPageConfig.mpdConfig.text
    }
    if (!mpdPageConfig.mpdConfig.slot || mpdPageConfig.mpdConfig.slot.length === 0) {
      delete mpdPageConfig.mpdConfig.slot
    } else {
      mpdPageConfig.mpdConfig.slot.forEach((item) => {
        optimizeMpdPageConfig(item)
      })
    }
    // 整理slot配置
    const comConfig: PageDom = <PageDom>library.getLibraryDataMap(mpdPageConfig.mpdConfig.component)
    if (comConfig.ext && comConfig.ext.componentConfig && comConfig.ext.componentConfig.length > 0) {
      comConfig.ext.componentConfig.forEach((item) => {
        if (mpdPageConfig.mpdConfig && mpdPageConfig.mpdConfig.configTmp) {
          const key = `${item.type}.${item.name}`
          if (
            !item.inputList ||
            item.inputList.length === 0 ||
            item.inputList[0].component === mpdPageConfig.mpdConfig.configTmp[key]
          ) {
            delete mpdPageConfig.mpdConfig.configTmp[key]
          }
        }
      })
    }
    if (!mpdPageConfig.mpdConfig.configTmp || Object.keys(mpdPageConfig.mpdConfig.configTmp).length === 0) {
      delete mpdPageConfig.mpdConfig.configTmp
    }
  }
  if (mpdPageConfig.children && mpdPageConfig.children.length > 0) {
    mpdPageConfig.children.forEach((item) => {
      optimizeMpdPageConfig(item)
    })
  } else {
    delete mpdPageConfig.children
  }
  delete mpdPageConfig.ext
  return mpdPageConfig
}
